//
// Created by Rory on 2020/10/5.
//线性表的物理结构实现
//

#ifndef DATA_STRUCTURE_PROGRAMMING_USING_C_SEQUENTIALLIST_H
#define DATA_STRUCTURE_PROGRAMMING_USING_C_SEQUENTIALLIST_H

//#define var(type,name) type name;

#include "../common.h"
/**
 * 顺序表
 * 容量到达上限时自动扩容，公式为:新容量 = 2*(旧容量 + 1) - 1
 * 使用方式：创建一个顺序表指针，然后调用InitSeqList()函数
 */
struct SequentialList;


typedef bool (*Equal) (void* e1, void* e2);

typedef struct{
    int elementSize;//数据元素大小
    size_t capacity;//容量
    size_t length;//已有元素长度

    int (*LocateElement) (struct SequentialList*,void*,Equal);
    void* (*GetElement) (struct SequentialList*,size_t);
    void (*Append)(struct SequentialList*,void* element);
    void (*IntPrint)(struct SequentialList*);

    void* data[0];
}SequentialList;
typedef SequentialList* SeqListPtr;


static bool ExpandList(SeqListPtr list);

//按值查找，返回位序
static int LocateElement(SeqListPtr list,void* element,Equal equal){
    for (int i = 0; i < list->length; ++i) {
        if(equal(list->data[i],element)){
            return i+1;
        }
    }
    return 0;
}

//按位序查找(从1开始)
static void* GetElement(SeqListPtr list,size_t location){
    if(location > 0 && location <= list->length){
        return list->data[location-1];
    }
    return NULL;
}

//插入
static bool InsertElement(SeqListPtr list,void* element){
    return true;
}

/*删除
 * returnedValue表示将删除元素地址给returnedValue
*/
static void DeleteElement(SeqListPtr list, int location, void* returnedValue){

}

//将数据按int类型打印
static void IntPrint(SeqListPtr list){
    for (int i = 0; i < list->length; ++i) {
        printf("%d ",*(int*)list->data[i]);
    }
    printf("\n");
}

static bool SeqAppend(SeqListPtr list, void* element){
    if(list->length == list->capacity){
        if(!ExpandList(list)){
            return false;
        }
    }
    list->data[list->length++] = element;
    return true;
}



bool InitSeqList(SeqListPtr* list,int capacity,int elementSize){
    (*list) = (SeqListPtr)malloc(sizeof(SequentialList) + elementSize*capacity);
    if(list == NULL){
        return false;
    }
    (*list)->capacity = capacity;
    (*list)->elementSize = elementSize;
    (*list)->length = 0;
    (*list)->GetElement = GetElement;
    (*list)->LocateElement = LocateElement;
    (*list)->Append = SeqAppend;
    (*list)->IntPrint = IntPrint;
    return true;
}

void DestroySeqList(SeqListPtr list){
    //释放结构体
    free(list);
}

bool ExpandList(SeqListPtr list){
    if(list == NULL){
        return false;
    }
    if(!realloc(list,sizeof(SequentialList) + list->elementSize* (2*(list->capacity+1)-1) )){
        return false;
    }
    list->capacity = list->elementSize* (2*(list->capacity+1)-1);
    return true;

}
#endif //DATA_STRUCTURE_PROGRAMMING_USING_C_SEQUENTIALLIST_H
